from __future__ import annotations

import hashlib

from django import forms

from payments import PaymentStatus

NEW = "new"
PROCESSING = "processing"
COMPLETED = "completed"
REJECTED = "rejected"
PROCESSING_REALIZATION_WAITING = "processing_realization_waiting"
PROCESSING_REALIZATION = "processing_realization"


class ProcessPaymentForm(forms.Form):
    id = forms.CharField(required=False)
    operation_number = forms.CharField(required=False)
    operation_type = forms.CharField(required=False)
    operation_status = forms.CharField(required=False)
    operation_amount = forms.CharField(required=False)
    operation_currency = forms.CharField(required=False)
    operation_withdrawal_amount = forms.CharField(required=False)
    operation_commission_amount = forms.CharField(required=False)
    is_completed = forms.CharField(required=False)
    operation_original_amount = forms.CharField(required=False)
    operation_original_currency = forms.CharField(required=False)
    operation_datetime = forms.CharField(required=False)
    operation_related_number = forms.CharField(required=False)
    control = forms.CharField(required=False)
    description = forms.CharField(required=False)
    email = forms.CharField(required=False)
    p_info = forms.CharField(required=False)
    p_email = forms.CharField(required=False)
    credit_card_issuer_identification_number = forms.CharField(required=False)
    credit_card_masked_number = forms.CharField(required=False)
    credit_card_brand_codename = forms.CharField(required=False)
    credit_card_brand_code = forms.CharField(required=False)
    credit_card_id = forms.CharField(required=False)
    channel = forms.CharField(required=False)
    channel_country = forms.CharField(required=False)
    geoip_country = forms.CharField(required=False)
    signature = forms.CharField(required=True)

    def __init__(self, payment, pin, **kwargs):
        super().__init__(**kwargs)
        self.pin = pin
        self.payment = payment

    def clean(self):
        cleaned_data = super().clean()
        if not self.errors:
            key_vars = (
                self.pin,
                cleaned_data.get("id", ""),
                cleaned_data.get("operation_number", ""),
                cleaned_data.get("operation_type", ""),
                cleaned_data.get("operation_status", ""),
                cleaned_data.get("operation_amount", ""),
                cleaned_data.get("operation_currency", ""),
                cleaned_data.get("operation_withdrawal_amount", ""),
                cleaned_data.get("operation_commission_amount", ""),
                cleaned_data.get("is_completed", ""),
                cleaned_data.get("operation_original_amount", ""),
                cleaned_data.get("operation_original_currency", ""),
                cleaned_data.get("operation_datetime", ""),
                cleaned_data.get("operation_related_number", ""),
                cleaned_data.get("control", ""),
                cleaned_data.get("description", ""),
                cleaned_data.get("email", ""),
                cleaned_data.get("p_info", ""),
                cleaned_data.get("p_email", ""),
                cleaned_data.get("credit_card_issuer_identification_number", ""),
                cleaned_data.get("credit_card_masked_number", ""),
                cleaned_data.get("credit_card_brand_codename", ""),
                cleaned_data.get("credit_card_brand_code", ""),
                cleaned_data.get("credit_card_id", ""),
                cleaned_data.get("channel", ""),
                cleaned_data.get("channel_country", ""),
                cleaned_data.get("geoip_country", ""),
            )
            key = "".join(key_vars)
            sha256 = hashlib.sha256()
            sha256.update(key.encode("utf-8"))
            key_hash = sha256.hexdigest()
            if key_hash != self.cleaned_data["signature"]:
                self._errors["signature"] = self.error_class(["Bad hash"])
            if int(cleaned_data["control"]) != self.payment.id:
                self._errors["control"] = self.error_class(["Bad payment id"])
        return cleaned_data

    def save(self, *args, **kwargs):
        status = self.cleaned_data["operation_status"]
        self.payment.transaction_id = self.cleaned_data["operation_number"]
        self.payment.save()
        if status == COMPLETED:
            self.payment.captured_amount = self.payment.total
            self.payment.change_status(PaymentStatus.CONFIRMED)
        elif status == REJECTED:
            self.payment.change_status(PaymentStatus.REJECTED)
